package com.anlogic.sdk.openocd.ui;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import com.anlogic.sdk.openocd.model.JtagCable;
import com.anlogic.sdk.openocd.model.RemoteTarget;
import com.anlogic.sdk.openocd.model.TargetModel;
import com.anlogic.sdk.openocd.utils.OpenocdUtils;

public class NewTargetDialog extends TitleAreaDialog {
	private static final int TEST_CONNECTION_ID = 1025;

	private Text targetText;
	private Button setAsDefaultButton;
	private Text hostText;
	private Text portText;

	private TargetModel model;
	private RemoteTarget target;

	private ExpandableComposite advanceComposite;
	private MultiCableDevicesWidget multiCableDevices;
	
	public NewTargetDialog(Shell parentShell, TargetModel model) {
		super(parentShell);
		setShellStyle(getShellStyle() | SWT.RESIZE);
		this.model = model;
		this.target = new RemoteTarget();
	}

	protected Control createButtonBar(Composite parent) {
		Control control = super.createButtonBar(parent);
		getButton(IDialogConstants.OK_ID).setEnabled(false);
		validate();
		return control;
	}

	protected void createButtonsForButtonBar(Composite parent) {
		createButton(parent, TEST_CONNECTION_ID, "Test Connection", false);
		super.createButtonsForButtonBar(parent);
	}

	private void enableOkButton(boolean flag) {
		Button button = getButton(IDialogConstants.OK_ID);
		if (button != null) {
			button.setEnabled(flag);
		}
	}

	protected Control createDialogArea(Composite parent) {
		setTitle("Target Connection Details");
		setMessage("New Target Connection");

		Composite container = new Composite(parent, SWT.DEFER);
		container.setLayout(new GridLayout(2, false));
		container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

		Label targetLabel = new Label(container, SWT.NULL);
		targetLabel.setText("Target Name:");
		targetText = new Text(container, SWT.BORDER);
		targetText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

		setAsDefaultButton = new Button(container, SWT.CHECK);
		setAsDefaultButton.setText("Set as default target");
		GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo((Control) setAsDefaultButton);

		Label hostLabel = new Label(container, SWT.NULL);
		hostLabel.setText("Host:");
		hostText = new Text(container, SWT.BORDER);
		hostText.setText("localhost");
		hostText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		target.setHost(hostText.getText());

		Label portLabel = new Label(container, SWT.NULL);
		portLabel.setText("Port:");
		portText = new Text(container, SWT.BORDER);
		portText.setText("3333");
		portText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		target.setPort(portText.getText());

		advanceComposite = new ExpandableComposite(container, ExpandableComposite.TREE_NODE);
		GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo((Control) advanceComposite);
		advanceComposite.setText("Advance");
		multiCableDevices = new MultiCableDevicesWidget(advanceComposite);
		advanceComposite.setClient(multiCableDevices.getContainer());
		
		addListeners();

		return (Control) parent;
	}

	private void addListeners() {
		targetText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				validate();
			}
		});

		setAsDefaultButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				validate();
			}
		});

		hostText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				validate();
			}
		});

		portText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				validate();
			}
		});

		advanceComposite.addExpansionListener(new ExpansionAdapter() {
			public void expansionStateChanged(ExpansionEvent e) {
				getShell().pack();
			}
		});
	}

	private void validate() {
		String targetName = targetText.getText();
		if (targetName.isEmpty()) {
			setErrorMessage("Enter Target Name");
			enableOkButton(false);
			return;
		}

		RemoteTarget oldTarget = model.getTarget(targetName);
		if (oldTarget != null) {
			setErrorMessage("Target with specified name already exists.");
			enableOkButton(false);
			return;
		}

		String host = hostText.getText();
		if (host.isEmpty()) {
			setErrorMessage("Enter Host Name");
			enableOkButton(false);
			return;
		}

		String port = portText.getText();
		if (port.isEmpty()) {
			setErrorMessage("Enter Port Name");
			enableOkButton(false);
			return;
		}

		try {
			Integer.parseInt(port);
		} catch (NumberFormatException numberFormatException) {
			setErrorMessage("Port number should be a number");
			enableOkButton(false);
			return;
		}
		
		target.setName(targetText.getText());
		target.setHost(hostText.getText());
		target.setPort(portText.getText());
		target.setAsDefault(setAsDefaultButton.getSelection());
		
		setErrorMessage(null);
		enableOkButton(true);
	}
	
	protected void okPressed() {
		JtagCable cable = multiCableDevices.getSelecionCable();
		if (cable != null) {
			target.setCable(cable);
		}
		model.addTarget(target);
		multiCableDevices.savePreferences();
		super.okPressed();
	}

	public RemoteTarget getTarget() {
		return this.target;
	}

	protected void buttonPressed(int buttonId) {
		if (buttonId == TEST_CONNECTION_ID) {
			String host = hostText.getText();
			String port = portText.getText();
			OpenocdUtils.testConnection(host, port);
		} else {
			super.buttonPressed(buttonId);
		}
	}
}
